home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
multidef.arc
/
MULTIDEF.C
Wrap
Text File
|
1987-04-13
|
19KB
|
471 lines
/*
** multidef.c - A program to scan a collection of .o and library files
** and search for multiply defined symbols.
** This can catch problems where a symbol is defined in your
** routine as well as in a scanned library (for example you
** have a roued executables have hunks
** in them that this program doesn't understand, besides the
** symbol information is gone from an executable anyway.
**
** Copyright (c) 1886, Paul Jatkowski.
*/
#include <stdio.h>
#include <fcntl.h>
/* defines for the different hunk types */
#define HUNK_UNIT 0x3e7 /* start of a program unit */
#define HUNK_NAME 0x3e8 /* name of hunk (optional) */
#define HUNK_CODE 0x3e9 /* block of code, possibly to be relocated */
#define HUNK_DATA 0x3ea /* block of initialized data, possibly relocated */
#define HUNK_BSS 0x3eb /* uninitialized data */
#define HUNK_RELOC32 0x3ec /* 32 bit relocation entries */
#define HUNK_RELOC16 0x3ed /* 16 bit pc relative relocation entries */
#define HUNK_RELOC8 0x3ee /* 8 bit pc relative relocation entries */
#define HUNK_EXT 0x3ef /* external symbol info ... see below */
#define HUNK_SYMBOL 0x3f0 /* symbol table info, optional, for debuggers */
#define HUNK_DEBUG 0x3f1 /* further debugging info */
#define HUNK_END 0x3f2 /* end of a hunk */
/* lattice 3.1 hunk types */
#define HUNK_DRELOC32 0x3f7 /* 32 bit data section relative relocation */
#define HUNK_DRELOC16 0x3f8 /* 16 bit data section relative relocation */
#define HUNK_DRELOC8 0x3f9 /* 8 bit data section relative relocation */
/* the following hunk defines are for load files */
#define HUNK_HEADER 0x3f3 /* info for loader ... lots of stuff in here */
#define HUNK_OVERLAY 0x3f5 /* overlay table for overlay programs */
#define HUNK_BREAK 0x3f6 /* end of overlay node */
/* defines for HUNK_EXT hunk
** These are the important ones for getting symbol define/reference info
*/
#define EXT_SYMB 0 /* symbol table */
#define EXT_DEF 1 /* relocatable definition */
#define EXT_ABS 2 /* absolute definition */
#define EXT_RES 3 /* resident library definition */
#define EXT_REF32 129 /* 32 bit reference to symbol */
#define EXT_COMMON 130 /* 32 bit reference to COMMON */
#define EXT_REF16 131 /* 16 bit reference to symbol */
#define EXT_REF8 132 /* 8 bit reference to symbol */
/* lattice 3.1 extra defines */
#define EXT_DREF32 133 /* 32 bit base relative to symbol */
#define EXT_DREF16 134 /* 16 bit base relative to symbol */
#define EXT_DREF8 135 /* 8 bit base relative to symbol */
#define MAXBUF 100 /* buffer for "get_and_flush" and "myread" */
long buf[MAXBUF];
/* operation flags */
int pr_def = 0; /* print symbol definition listing */
int pr_ref = 0; /* print symbol reference listing */
/* defines for t_insert routine (binary tree) */
struct t_node {
struct tnode *right;
struct tnode *left;
char *key; /* symbol name */
char *aux1; /* file name */
char *aux2; /* module name */
};
typedef struct t_node T_node;
/* declarations for forward referenced routines */
T_node *t_insert();
void save_def();
void
myread(fd,ptr,sz)
int fd,sz;
char *ptr;
{
if (read(fd,ptr,sz) != sz)
{
printf("short read: aborting\n");
exit(10);
}
}
/* read n LONGS from the object file, used to flush unnecessary sections.
** I suppose that a seek would work also...... */
void
get_and_flush(objfile,n)
int objfile,n;
{
int n1;
n *= 4;
while (n > 0)
{
n1 = n > MAXBUF ? MAXBUF : n;
n -= n1;
myread(objfile,buf,n1);
}
}
/*
** given a object or library file name, read it and find symbol entries.
** print references or definitions if the flags are set. Collect the
** to look for multiple defines
*/
void
procfile(fname)
char *fname;
{
int moretodo = 1;
long d1 = -1 ,d2;
int ext_type;
char curhunk[100];
char curname[100];
int hunkend = 0;
int objfile;
if (pr_def || pr_ref)
printf("\t=========== processing %s ============\n",fname);
if ( (objfile = open(fname,O_RDONLY)) < 0)
{
perror("can't open input file");
poserr("amiga error");
return;
}
while (moretodo)
{
/* read what is hopefully a hunk type */
if (read(objfile,(char *)&d1,sizeof(d1)) != sizeof(d1))
{
if (!hunkend)
printf("Unexpected end of file! (no hunk end)\n");
moretodo = 0;
continue;
}
hunkend = 0;
switch(d1)
{
case HUNK_UNIT: /* 3e7 Start of program unit */
myread(objfile,&d1,sizeof(d1));
myread(objfile,buf,d1*4);
buf[d1] = 0;
strcpy(curhunk,(char *)buf);
#ifdef DEBUG
printf("hunk unit: %s\n",curhunk);
#endif
break;
case HUNK_NAME: /* 3e8 Name of a hunk */
myread(objfile,&d1,sizeof(d1));
myread(objfile,buf,d1*4);
buf[d1] = 0;
strcpy(curname,(char *)buf);
#ifdef DEBUG
printf("hunk name: %s\n",curname);
#endif
break;
case HUNK_CODE: /* 3e9 Code segment */
case HUNK_DATA: /* 3ea Initialized Data segment */
myread(objfile,&d1,sizeof(d1));
#ifdef DEBUG
printf("code/data hunk length=%d\n",d1);
#endif
get_and_flush(objfile,d1);
break;
case HUNK_BSS: /* 3eb Unitialized Data segment */
myread(objfile,&d1,sizeof(d1));
#ifdef DEBUG
printf("bss section length=%d\n",d1);
#endif
break;
case HUNK_RELOC32: /* 3ec 32-bit relocation list */
case HUNK_RELOC16: /* 3ed 16-bit PC-relative relocation info */
case HUNK_RELOC8: /* 3ee 8-bit PC-relative relocation info */
case HUNK_DRELOC32:
case HUNK_DRELOC16:
case HUNK_DRELOC8:
#ifdef DEBUG
printf("reloc hunk type 0x%x\n",d1);
#endif
myread(objfile,&d1,sizeof(d1));
while (d1 != 0)
{
myread(objfile,&d2,sizeof(d2));
get_and_flush(objfile,d1);
myread(objfile,&d1,sizeof(d1));
}
break;
case HUNK_EXT: /* 3ef External symbol info */
#ifdef DEBUG
printf("hunk ext\n");
#endif
myread(objfile,&d1,sizeof(d1));
while (d1 != 0)
{
ext_type = (d1 >> 24) & 0xff;
d1 &= 0xffffff;
switch(ext_type)
{
case EXT_SYMB: /* symbol table */
get_and_flush(objfile,d1+1);
break;
case EXT_DEF: /* reloc def */
case EXT_ABS: /* abs def */
case EXT_RES: /* resident lib */
myread(objfile,buf,d1*4);
buf[d1] = 0;
if (pr_def)
printf("DEF %-45.45s: %s\n",(char *)buf,curhunk);
save_def(fname,curhunk,(char *)buf);
get_and_flush(objfile,1);
break;
case EXT_REF32: /* 32 bit ref */
case EXT_REF16: /* 16 bit ref */
case EXT_REF8: /* 8 bit ref */
case EXT_DREF32:
case EXT_DREF16:
case EXT_DREF8:
myread(objfile,buf,d1*4);
buf[d1] = 0;
if (pr_ref)
printf("REF %-45.45s: %s\n",(char *)buf,curhunk);
myread(objfile,&d1,sizeof(d1));
get_and_flush(objfile,d1);
break;
case EXT_COMMON: /* 32 bit ref */
myread(objfile,buf,d1*4);
buf[d1] = 0;
if (pr_def)
printf("COM %-45.45s: %s\n",(char *)buf,curhunk);
save_def(fname,curhunk,(char *)buf);
myread(objfile,&d1,sizeof(d1));
myread(objfile,&d1,sizeof(d1));
get_and_flush(objfile,d1);
break;
default:
printf("ERROR: unknown HUNK_EXT 0x%x\n",d1);
}
myread(objfile,&d1,sizeof(d1));
}
break;
case HUNK_SYMBOL: /* 3f0 Symbol table info */
myread(objfile,&d1,sizeof(d1));
while (d1 != 0)
{
get_and_flush(objfile,d1+1);
myread(objfile,&d1,sizeof(d1));
}
break;
case HUNK_DEBUG: /* 3f1 Debug data */
myread(objfile,&d1,sizeof(d1));
get_and_flush(objfile,d1);
break;
case HUNK_END: /* 3f2 End of this hunk */
hunkend++;
break;
case HUNK_HEADER: /* 3f3 hunk summary info for loader */
case HUNK_OVERLAY: /* 3f5 overlay table info */
case HUNK_BREAK: /* 3f6 end of overlay node */
default:
printf("ERROR: can't handle hunk 0x%x\n",d1);
}
}
close(objfile);
}
#define MAXEXP 100
void
main(argc,argv)
int argc;
char *argv[];
{
int i,j;
int matches;
char names[3000]; /* for expanded file names */
char *namep[MAXEXP]; /* array for pointers to file names */
/* parse args, set global flags */
if ( argc < 2)
{
printf("usage: %s [-d] [-r] objfile1 ojbfile2 ...\n",argv[0]);
exit(1);
}
/*
** Arg processing, nothing great, but sufficient.
*/
for (i = 1 ; i < argc ; i++)
{
if (strcmp(argv[i],"-r") == 0)
{
pr_ref = 1;
continue;
}
if (strcmp(argv[i],"-d") == 0)
{
pr_def = 1;
continue;
}
/*
** not an arg, must be an object file.
** Lattice 3.10 provides the getfnl routine that will take
** an amigados pattern and build a list of matching files.
** It this is not available, the input file name could be
** passed directly to procfile, but the wild card expansion
** is nice.
*/
matches = getfnl(argv[i],names,sizeof(names),0);
if (matches > 0)
{
/* set up pointer array to point to each string */
if (strbpl(namep,MAXEXP,names) != matches)
{
printf("%s - expansion overflow\n",argv[i]);
continue;
}
/* sort the pointers, just to be nice */
strsrt(namep,matches);
/* process the files .... */
for ( j = 0 ; j < matches ; j++)
procfile(namep[j]);
}
else
{
printf("expansion failed for %s\n",argv[i]);
}
}
}
/*
** build a tree node and call t_insert to put it into the tree of defs.
** if t_insert returns 0, this is the only definition of the symbol.
** if t_insert returns -1, there was some unexpected error in t_insert.
** if t_insert returns anything else, it's a pointer to a node containing
** the first definiton of the symbol. The current entry is not saved
** in the tree.
*/
void
save_def(fname,hunk,sym)
char *fname, *hunk, *sym;
{
/* this routine does the work of building an internal symbol table */
static T_node t1;
static T_node *tree = (T_node *)0;
T_node *rval;
t1.key = sym;
t1.aux1 = fname;
t1.aux2 = hunk;
t1.right = (T_node *)0;
t1.left = (T_node *)0;
rval = t_insert(&tree,&t1);
if ((int) rval != 0 && (int)rval != -1)
{
printf("%s defined in %s(%s) and %s(%s)\n",
sym,rval->aux1,rval->aux2,fname,hunk);
}
}
/*
** Insert a node into a binary tree. The tree built is never walked so only
** the insert routine is needed
*/
T_node *
t_insert(head,node)
T_node **head; /* note double indirection, this simplfies the code later */
T_node *node;
{
T_node *newnode;
static char *O_aux1 = (char *)0;
static char *O_aux2 = (char *)0;
int result;
#ifdef DEBUG
printf("key=%s aux1=%s aux2=%s\n",node->key,node->aux1,node->aux2);
#endif
/* check for null head pointer, if so create first node */
if (*head == (T_node *)0)
{
newnode = (T_node *)malloc(sizeof(T_node));
if (newnode == (T_node *)0)
return((T_node *)-1);
newnode->key =
(char *) malloc(strlen(node->key)+1);
strcpy(newnode->key,node->key);
newnode->aux1 = O_aux1 = (char *)malloc(strlen(node->aux1)+1);
strcpy(newnode->aux1,node->aux1);
newnode->aux2 = O_aux2 = (char *)malloc(strlen(node->aux2)+1);
strcpy(newnode->aux2,node->aux2);
#ifdef DEBUG
printf ("newnode =0x%x\n",newnode);
#endif
newnode->right = (T_node *)0;
newnode->left = (T_node *)0;
*head = newnode;
return(0);
}
/* walk the tree to find a good spot */
while (*head != (T_node *)0)
{
#ifdef DEBUG
printf ("TOL: head=0x%x *head=0x%x compare <%s> <%s>\n",
head,*head,(*head)->key,node->key);
#endif
if ( (result = strcmp((*head)->key,node->key)) == 0)
{
return(*head); /* return pointer to dup node */
}
#ifdef DEBUG
printf ("result=%d\n",result);
#endif
if (result >0)
head = (T_node **)&(*head)->right;
else
head = (T_node **)&(*head)->left;
}
#ifdef DEBUG
printf ("EOL: head=0x%x *head=0x%x\n",head,*head);
#endif
/* didn't find it, link it in....
** only allocate new space for file and module name if different than
** last one remembered, otherwise use the previous string */
if ( (*head = (T_node *)malloc(sizeof(T_node))) == (T_node *)0)
{
printf("can't allocate space for node!\n");
return((T_node *)0);
}
(*head)->key = (char *)malloc(strlen(node->key)+1);
strcpy((*head)->key,node->key);
if (strcmp(node->aux1,O_aux1) == 0)
(*head)->aux1 = O_aux1; /* same thing! */
else
{
(*head)->aux1 = (char *)malloc(strlen(node->aux1)+1);
strcpy((*head)->aux1,node->aux1);
}
if (strcmp(node->aux2,O_aux2) == 0)
(*head)->aux2 = O_aux2; /* same thing! */
else
{
(*head)->aux2 = (char *)malloc(strlen(node->aux2)+1);
strcpy((*head)->aux2,node->aux2);
}
(*head)->right = (T_node *)0;
(*head)->left = (T_node *)0;
return((T_node *)0);
}
r array to point to each string */
if (strbpl(namep,MAXEXP